package dcpb.re.encryption;

import java.util.*;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.AbstractMap.SimpleEntry;

import it.unisa.dia.gas.jpbc.Element;
import it.unisa.dia.gas.plaf.jpbc.field.curve.CurveElement;
import it.unisa.dia.gas.plaf.jpbc.field.z.ZrElement;

public class Fabric {
	private  PubParams p;

    private List<Element> mu;
    private Map<Element,Element> skMap;
    private ZrElement MSK;
    ProxyReEncrypt  d=new ProxyReEncrypt ();
    private Element A;
    public List<Element> getIDs(){
    	return mu;
    }
    
    public void saveIDToFile(List<Element> ids) throws IOException, ClassNotFoundException {
    	List<byte[]> idbytes=new LinkedList<>();
    	for(Element id:ids) {
    		idbytes.add(id.toBytes());
    	}
    	String path="data/ids";
    	FileOutputStream fwriter = new FileOutputStream(path);
    	ObjectOutputStream objectOutputStream = new ObjectOutputStream(fwriter);
    	objectOutputStream.writeObject(idbytes);
    	
    }
    
//    public Fabric() {
//    	SimpleEntry<PubParams,Element> retMap=d.setup();//CA ����ϵͳ����
//    	PubParams p=retMap.getKey();
//    	SystemProperty.writeProperties(keyname, keyvalue);
//    }
	public Fabric(PubParams p,int m,int t,Element MSK) {
		// TODO Auto-generated constructor stub
		
		this.p=p;
		this.skMap=new HashMap<>();

		this.MSK = (ZrElement) MSK;
		mu=new LinkedList<>();
	}
	public List KeyGen() {
		   
		   Element ID_i=p.Zr.newRandomElement();
		   mu.add(ID_i);
		   SimpleEntry<Element,Element> ski=d.KeyGen(p,MSK,ID_i);
		   skMap.put(ID_i, ski.getValue());
		   List<Element> ret=new ArrayList<>(3);
		   ret.add(ID_i);
		   ret.add(ski.getKey());
		   ret.add(ski.getValue());
//		   Map<String,Element> map=new HashMap<>();
//		   map.put("ID", ID_i);
//		   map.put("sk_1",ski.getKey());
//		   map.put("sk_2", ski.getValue());
		   return ret;
	}
	public List<Element> aggregate(List<Element> mu1){// Zr
		List<Element> P=new LinkedList<Element>();
		ZrElement A1=MSK.duplicate().add(p.hash(mu1.get(0).duplicate()));
		P.add(A1);
		for(int i=1;i<mu1.size();i++) {
			A1=A1.duplicate().mul(MSK.duplicate().add(p.hash(mu1.get(i))));
			P.add(A1);
		}
		return P;
	}
	public void setA(List<Element> mu1) {
		ZrElement A=MSK.duplicate().add(p.hash(mu1.get(0).duplicate()));
		for(int i=1;i<mu1.size();i++) {
			A=A.duplicate().mul(MSK.duplicate().add(p.hash(mu1.get(i).duplicate())));
		}
		this.A=A;
		//d.writeFile("data/A", A.toBytes());
		
	}
	public Element getA() {
		return this.A;
	}
	
	public Fabric init() {
		ProxyReEncrypt  d=new ProxyReEncrypt ();
		
		int m=5,t=3;
		SimpleEntry<PubParams,Element> retMap=d.setup();//CA ����ϵͳ����
		PubParams p=retMap.getKey();
		d.save(p);
		SystemProperty.writeProperties("m", "5");
		SystemProperty.writeProperties("t", "3");
		Fabric f=new Fabric(p,m,t,retMap.getValue());
		return f;
	}
	public static void main(String[] args) {
		
	}
}
